/*
 * Copyright 2017 hv0912
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.vimhe.ezimp2.config.support;

import com.vimhe.ezimp2.config.AbstractConfigSource;
import com.vimhe.ezimp2.config.bean.ColumnConfig;
import com.vimhe.ezimp2.config.bean.FileConfig;
import com.vimhe.ezimp2.config.bean.FormatterConfig;
import com.vimhe.ezimp2.config.bean.RowConfig;
import com.vimhe.ezimp2.config.bean.SheetConfig;
import com.vimhe.ezimp2.config.bean.ValidatorConfig;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

import java.io.InputStream;

/**
 * 存储为 XML 形式的配置源
 *
 * @author Vimhe
 */
public final class XmlConfigSource extends AbstractConfigSource {

    /**
     * 配置文件路径，默认为classes根目录下的“importConfig.xml”
     */
    private String configLocation;

    public XmlConfigSource() {
        configLocation = "ezimp2Config.xml";
    }

    public XmlConfigSource(String configLocation) {
        this.configLocation = configLocation;
    }

    @Override
    protected void process() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        try (InputStream xmlInputStream = classLoader.getResourceAsStream(configLocation)) {
            if (xmlInputStream != null) {
                InputSource inputSource = new InputSource(xmlInputStream);
                XMLReader xmlReader = XMLReaderFactory.createXMLReader();
                xmlReader.setContentHandler(new XmlConfigSource.ConfigReader());
                xmlReader.parse(inputSource);
            }
        }
    }

    private class ConfigReader extends DefaultHandler {
        private String fileIndex;
        private Integer sheetIndex;
        private String cellIndex;

        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            switch (qName) {
                case "configuration":
                    read();
                    break;
                case "file":
                    FileConfig fileConfig = new FileConfig();
                    fileConfig.setIndex(attributes.getValue("index"));
                    fileConfig.setPath(attributes.getValue("path"));
                    fileConfig.setFormat(attributes.getValue("format"));

                    fileIndex = fileConfig.getIndex();
                    read(fileConfig);
                    break;
                case "sheet":
                    SheetConfig sheetConfig = new SheetConfig();
                    sheetConfig.setIndex(attributes.getValue("index"));
                    sheetConfig.setTable(attributes.getValue("table"));
                    sheetConfig.setCreate(attributes.getValue("create"));

                    sheetIndex = sheetConfig.getIndex();
                    read(fileIndex, sheetConfig);
                    break;
                case "row":
                    RowConfig rowConfig = new RowConfig();
                    rowConfig.setStart(attributes.getValue("start"));
                    rowConfig.setEnd(attributes.getValue("end"));

                    read(fileIndex, sheetIndex, rowConfig);
                    break;
                case "column":
                    ColumnConfig columnConfig = new ColumnConfig();
                    columnConfig.setIndex(attributes.getValue("index"));
                    columnConfig.setColumn(attributes.getValue("column"));
                    columnConfig.setType(attributes.getValue("type"));
                    columnConfig.setReadable(attributes.getValue("readable"));

                    cellIndex = columnConfig.getIndex();
                    read(fileIndex, sheetIndex, columnConfig);
                    break;
                case "validator":
                    ValidatorConfig validatorConfig = new ValidatorConfig();
                    validatorConfig.setName(attributes.getValue("name"));
                    validatorConfig.setValue(attributes.getValue("value"));
                    validatorConfig.setMessage(attributes.getValue("message"));

                    read(fileIndex, sheetIndex, cellIndex, validatorConfig);
                    break;
                case "formatter":
                    FormatterConfig formatterConfig = new FormatterConfig();
                    formatterConfig.setName(attributes.getValue("name"));
                    formatterConfig.setValue(attributes.getValue("value"));
                    formatterConfig.setMessage(attributes.getValue("message"));

                    read(fileIndex, sheetIndex, cellIndex, formatterConfig);
                    break;
                default:
                    break;
            }
        }

    }

}
